#include "StdAfx.h"
#include "vqmlcompiler.h"

#include "vblank.h"
#include "vcontrol.h"
#include "vstyle.h"
#include "vdata.h"

VQMLCompiler::VQMLCompiler(QObject *parent)
	: QObject(parent)
{
	qmlRegisterType<VAbstractData>();
	qmlRegisterUncreatableType<VAbstractControl>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V, VBLANK_MIN_V, qPrintable(VCTRL_PROP), "###");
	qmlRegisterType<VBlank>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V, VBLANK_MIN_V, qPrintable(VCTRL_BLANK));
	qmlRegisterType<VStyle>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V, VBLANK_MIN_V, qPrintable(VCTRL_STYLE));
	qmlRegisterType<VTime>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V, VBLANK_MIN_V, qPrintable(VCTRL_TIME));
	qmlRegisterType<VDate>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V, VBLANK_MIN_V, qPrintable(VCTRL_DATE));
	qmlRegisterType<VString>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V, VBLANK_MIN_V, qPrintable(VCTRL_STRING));
	qmlRegisterType<VInteger>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V, VBLANK_MIN_V, qPrintable(VCTRL_INTEGER));
	qmlRegisterType<VReal>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V, VBLANK_MIN_V, qPrintable(VCTRL_REAL));
	//qmlRegisterType<VLineBreak>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V, VBLANK_MIN_V, qPrintable(VCTRL_BR));
	qmlRegisterType<VLine>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V, VBLANK_MIN_V, qPrintable(VCTRL_LINE));
	qmlRegisterType<VLineEdit>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V, VBLANK_MIN_V, qPrintable(VCTRL_LINEEDIT));
	qmlRegisterType<VListEdit>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V, VBLANK_MIN_V, qPrintable(VCTRL_LISTEDIT));
	//qmlRegisterType<VIntEdit>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V, VBLANK_MIN_V, qPrintable(VCTRL_INTEDIT));
	//qmlRegisterType<VDoubleEdit>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V, VBLANK_MIN_V, qPrintable(VCTRL_DOUBLEEDIT));
	//qmlRegisterType<VDateEdit>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V, VBLANK_MIN_V, qPrintable(VCTRL_DATEEDIT));
	//qmlRegisterType<VTimeEdit>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V, VBLANK_MIN_V, qPrintable(VCTRL_TIMEEDIT));
	//qmlRegisterType<VComment>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V, VBLANK_MIN_V, qPrintable(VCTRL_COMMENT));
	qmlRegisterType<VTextEdit>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V, VBLANK_MIN_V, qPrintable(VCTRL_TEXTEDIT));
	qmlRegisterType<VImage>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V, VBLANK_MIN_V, qPrintable(VCTRL_IMAGE));
	qmlRegisterType<VTable>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V, VBLANK_MIN_V, qPrintable(VCTRL_TABLE));
	qmlRegisterType<VCell>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V, VBLANK_MIN_V, qPrintable(VCTRL_CELL));
	//
	qmlRegisterType<VFLayout>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V, VBLANK_MIN_V, qPrintable(VCTRL_FLAYOUT));
	qmlRegisterType<VHLayout>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V, VBLANK_MIN_V, qPrintable(VCTRL_HLAYOUT));
	qmlRegisterType<VTableRow>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V, VBLANK_MIN_V, qPrintable(VCTRL_TABLEROW));
	qmlRegisterType<VTableLayout>(qPrintable(VCTRL_LIB_NAME), VBLANK_MAJ_V, VBLANK_MIN_V, qPrintable(VCTRL_TABLELAYOUT));
}

VQMLCompiler::~VQMLCompiler()
{
}

VBlank* VQMLCompiler::execute(const QString& script, const QUrl& url)
{
	if (!m_qmlEngine)
	{
		m_qmlEngine.reset(new QDeclarativeEngine);
		connect(m_qmlEngine.get(), SIGNAL(warnings(const QList<QDeclarativeError>&)), this, SLOT(qmlWarnings(const QList<QDeclarativeError>&)));
	}

	m_qmlComponent.reset(new QDeclarativeComponent(m_qmlEngine.get(), this));
	
	QString s(SCRIPT_HEADER);
	s.append(script);
	s.append(SCRIPT_FOOTER);

	QUrl u(url);
	if (u.isEmpty())
		u.setPath("dummy.qml");
	
	m_qmlComponent->setData(s.toUtf8(), u);

	VBlank* b = qobject_cast<VBlank*>(m_qmlComponent->create());

	if (m_qmlComponent->isError())
	{
		//m_errors = m_qmlComponent->errors();		
		return 0;
	}

	b->setControlParent();
	return b;
}

QList<QDeclarativeError> VQMLCompiler::errors() const
{
	return m_qmlComponent->errors();
}

QPoint VQMLCompiler::errorsToPos(const QList<QString>& errors)
{
	QList<QString> el = errors[0].split(':');

	int line = 0;
	int column = 0;

	if (el.count() >= 2)
		line = el[1].toInt();

	if (el.count() >= 3)
		column = el[2].toInt();

	int addLines = SCRIPT_HEADER.split("\n").count();

	return QPoint(column-1, line-addLines);
}

void VQMLCompiler::qmlWarnings(const QList<QDeclarativeError>& w)
{
	emit warnings(w);
}